iT邦幫忙

2023 iThome 鐵人賽

DAY 27
0
SideProject30

用 Rails 打造你的電商網站系列 第 27

Day 27 - 發大財之前要做好準備

  • 分享至 

  • xImage
  •  

前置作業:訂單 CRUD

接下來就要來串金流囉,我們採用藍新金流

申辦測試帳號

在串金流以前,我們要先去藍新測試網站申辦帳號

申辦之後要記得去開立商店,並且拿到下列資料

Hash KeyHash IV商店代號

之後我們才有辦法打 API 到藍新金流那邊進行金流作業

由於這是對外的 API ,也算是一個服務,

所以我會使用 service object 來做

建立 Newebpay module

我們會新增 newebpay.rb 的檔案,在初始化的時候會帶入一些參數

當我們要打 API 過去藍新金流時,會需要 Hash KeyHash IV商店代號

Hash KeyHash IV 可以讓藍新來核對身份,如果是一致的,就可以繼續進行交易,

否則隨便一個人都可以中途攔截交易

那我們就先將它們放到初始化方法中

# app/service/newebpay.rb

class Newebpay
  def initialize
    @key = ENV["HASH_KEY"]
    @iv = ENV["HASH_IV"]
    @merchant_id = ENV["MERCHANT_ID"]
  end
end

定義交易資料

接著我們要設定傳送到金流系統的資料了

一樣是要在初始化的時候就要傳送進去,所以我們要在 initialize 設定

並且讓他要可以被其他方法存取及修改

# app/service/newebpay.rb

class Newebpay
  attr_accessor :info
  
  def initialize
    @key = ENV["HASH_KEY"]
    @iv = ENV["HASH_IV"]
    @info = {}
    @merchant_id = ENV["MERCHANT_ID"]
  end
end

接著我們來設定一下 info 中的參數

MerchantOrderNoAmtItemDescEmail

這些都是要放 order 裡面的資料,

分別是訂單編號、總金額、商品名稱、消費者信箱,

如果還需要放其他參數,可以參閱手冊

# app/service/newebpay.rb

def set_info(order)  
  info[:MerchantID] = @merchant_id
  info[:MerchantOrderNo] = order.slug
  info[:Amt] = order.amount 
  info[:ItemDesc] = order.name 
  info[:Email] = order.email 
  info[:TimeStamp] = Time.now.to_i 
  info[:RespondType] = "JSON"
  info[:Version] = "1.6"
  info[:ReturnURL] = ""
  info[:NotifyURL] = ""
  info[:LoginType] = 0 
  info[:CREDIT] =  1,
  info[:VACC] = 1
end

接著我們要在初始化的時候就把這些參數設定好

initialize 設定一個參數,讓 order 可以傳進來

並且作為 set_info 的參數,把 order 的資訊塞到 info

# app/service/newebpay.rb

def initialize(params)
  @key = ENV["HASH_KEY"]
  @iv = ENV["HASH_IV"]
  @info = {}
  @merchant_id = ENV["MERCHANT_ID"]
  set_info(params)
end

針對 交易資料 / Hash Key / Hash IV 雜湊

在這之前我們先把交易資料轉變成 query string

# app/service/newebpay.rb

def encoded_info
  URI.encode_www_form(info)
end

接著丟去雜湊,藍新所用的是 AES-256 雜湊,

讓這串機密資料不容易被猜到,增加機密性

# app/service/newebpay.rb

private

def encrypt(params)
  # 使用 AES256 來雜湊
  cipher = OpenSSL::Cipher::AES256.new(:CBC)
  
  # 設定 cipher 為加密模式
  cipher.encrypt
  
  # 將 @key 及 @iv 塞進 cipher
  cipher.key = @key
  cipher.iv = @iv
  
  # 進行加密
  encrypted = cipher.update(params.to_query) + cipher.final
  
  # 將二進位轉為十六進位 (主要是讓電腦好閱讀)
  return encrypted.unpack('H*')[0] 
end

我們之後還得使用這包資料,

把它整理成一個方法,看起來會更簡潔一點

def trade_info
  encrypt(encoded_info)
end

將已雜湊過的資料來產生檢查碼

接下來要將剛剛雜湊的結果產出檢查碼

為什麼要產出檢查碼?

  1. 多一層防護
  2. 避免單筆訂單重複交易

藍新規定產出檢查碼之前,要把 AES 雜湊過的字串改成規定的格式

Hash Key 要改成 HashKey=(the HashKey)&
Hash IV 要改成 HashIV=(the HashIV)

需要將 Hash Key / Hash IV / trade_info(剛剛雜湊過的資料) 再做一次雜湊

# app/service/newebpay.rb

def generate_aes_sha256(key, iv, trade_info)
  str = "HashKey=#{key}&#{trade_info}&HashIV=#{iv}"
end

再來就可以用 SHA256 產出檢查碼,雜湊後要記得轉成大寫,手冊上有寫唷

# app/service/newebpay.rb

def generate_aes_sha256(key, iv, trade_info)
  str = "HashKey=#{key}&#{trade_info}&HashIV=#{iv}"
  Digest::SHA256.hexdigest(str).upcase
end

接著也把它整理成一個方法

def trade_sha
  generate_aes_sha256(@key, @iv, trade_info)
end

明天我們會發送 request ,相關設定也會一併帶到


上一篇
Day 26 - 測測你寫的程式碼!
下一篇
Day 28 - 準備掏錢的前奏
系列文
用 Rails 打造你的電商網站30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言